#include <stdio.h>
#include <GL/glut.h>

#include "../utils/Defines.h"
#include "../baseclass/StateUser.h"
#include "../spec/SkyObject.h"
#include "../spec/ElicObject.h"
#include "../spec/WorldObject.h"
#include "../spec/MapObject.h"
#include "../spec/FotoIdObject.h"
#include "../spec/ExplosionObject.h"
#include "../spec/TargetObject.h"
#include "GameControlHandler.h"
#include "LightHandler.h"
#include "CameraHandler.h"



//gestori di effetti
GameStatus state;                  //stato del gioco
LightHandler light(&state);        //gestore delle luci
CameraHandler camera(&state);      //gestore della camera
TextureHandler texture(&state);    //gestore delle texture
GameControlHandler game(&state);   //gestore fasi di gioco


//oggetti do gioco
ElicObject elic(&state);                   //elicottero
SkyObject sky(&state);                     //cielo
WorldObject world(&state);                 //mondo 3d
MapObject map(&state);                     //mappa di riferimento
FotoIdObject fotoid(&state);               //fotoid 



void RenderScene();
void RenderScene_Paused();
void RenderScene_Start();
void RenderScene_End();
void tastiera_normale_inizio_giu(unsigned char tasto, int x, int y);
void tastiera_normale_pausa_giu(unsigned char tasto, int x, int y);
void tastiera_normale_fine_giu(unsigned char tasto, int x, int y);
void tastiera_normale_giu(unsigned char tasto, int x, int y);
void tastiera_normale_su(unsigned char tasto, int x, int y);
void tastiera_speciale_giu(int tasto, int x, int y);
void tastiera_speciale_su(int tasto, int x, int y);
void mouse_movimento(int x, int y);
void mouse_buttons(int b , int s , int x, int y);
void ridimensiona(int anchop, int altop);
void elabora_tempo_vuoto();
void Load_New_Game();






int main(int argc, char** argv) 
{

	
   //queste vanno prima di glutinit
    glutInitDisplayMode(GLUT_ACCUM | GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
    glutInitWindowPosition(100, 0);
    glutInitWindowSize(LARG_SCR, ALT_SCR);
    glutInit(&argc,argv);
    glutCreateWindow("BuLLeT PRooF (Demo version 0.33)");    
    
	
	
   
    //abilita le impostazioni opengl
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);                             // Il tipo di Depth Testing da fare
    glShadeModel(GL_SMOOTH);  
    glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST );
     
    
    //carico le textures
    game.Init();
   state.th = new TextureHandler(&state);
    state.th->Init();
    
    //carico il gioco 
    Load_New_Game();
   
    glutMainLoop();
 
    return 0;
}




void Load_New_Game()
{
   //inizializza gli oggetti
    state.LoadNewState();
    sky.Init();
    world.Init();
    elic.Init();
    map.Init();
    fotoid.Init();
    state.map = &map;
    state.fotoid = &fotoid;
    state.world = &world;
    state.targ = new TargetObject(&state);
    state.targ->Init();
    
    //inizializzo i gestori 
    camera.Init();
    camera.Camera_Fullscreen(); 
    light.Init();
    
    //altezza     
    state.cam_posY = world.GetHeight(state.cam_posX,state.cam_posZ);
    
    
    glClearColor(0,0,0,0);
    glutKeyboardFunc(tastiera_normale_inizio_giu);
    glutDisplayFunc(RenderScene_Start);
    glutReshapeFunc(ridimensiona);
   
}

void RenderScene_Paused()
{ 
    game.Draw_Paused();
}

void RenderScene_Start()
{
    game.Draw_Now_Loading();
}

void RenderScene_End()
{
    game.Draw_End_Of_Game();
}

void RenderScene() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) ;
    
    
    glLoadIdentity();
    
    state.cam_fut_posY = world.GetHeight(state.cam_posX,state.cam_posZ) - state.fly_height;
    
    camera.Move();
    light.Move();
    sky.Draw();
    world.Draw();
    state.targ->Draw();
    elic.Draw();
      
    
    
    
    //disegno i fumini      
    for (int i = 0;i < state.smoke_counter;i++)
              if(state.smokes[i] != NULL && state.smokes[i]->visible)  
              state.smokes[i]->Draw();
              
    //disegno le esplosioni
    for (int i = 0;i < state.explosions_counter;i++)
          if(state.explosions[i] != NULL && state.explosions[i]->visible)  
          state.explosions[i]->Draw();
    
   
    //disegno i le polveri dei proiettili      
    for (int i = 0;i < state.dust_counter;i++)
              if(state.dusts[i] != NULL && state.dusts[i]->visible) 
               state.dusts[i]->Draw();

    map.Draw(); 
    fotoid.Draw();
    camera.MotionBlur();

    
glutSwapBuffers();
}


void tastiera_normale_inizio_giu(unsigned char tasto, int x, int y) 
{
    
    glutDisplayFunc(RenderScene);
    glutKeyboardFunc(tastiera_normale_giu);
    glutKeyboardUpFunc(tastiera_normale_su);
    glutSpecialFunc(tastiera_speciale_giu);
    glutSpecialUpFunc(tastiera_speciale_su);
    glutMotionFunc(mouse_movimento);
    glutMouseFunc(mouse_buttons);
    glutIdleFunc(elabora_tempo_vuoto);
    time(&(state.time));
    camera.SelFarPos();
}

void tastiera_normale_pausa_giu(unsigned char tasto, int x, int y)
{
  switch(tasto) {
    case  27:  
       camera.Restore();
       game.Set_Pause_time();
       glutDisplayFunc(RenderScene);
       glutKeyboardFunc(tastiera_normale_giu);
       glutIdleFunc(elabora_tempo_vuoto);
       glutKeyboardUpFunc(tastiera_normale_su);
       glutSpecialFunc(tastiera_speciale_giu);
       glutSpecialUpFunc(tastiera_speciale_su);
       glutMotionFunc(mouse_movimento);
    break;
    
    case 127: glutLeaveGameMode();   exit(0) ;   break; //la n
    
    case 110:
         Load_New_Game();
    break;
  }
}

void tastiera_normale_fine_giu(unsigned char tasto, int x, int y)
{
   switch(tasto) { 
    case 127: glutLeaveGameMode();   exit(0) ;   break; //la n
    
    case 110:
         state.gameend;
         Load_New_Game();
    break;
  }
}


void tastiera_normale_giu(unsigned char tasto, int x, int y) {
 //     printf("\ntasto %c %d",tasto,tasto);

switch(tasto) {
    case  27:  //pausa
       camera.Save();
       game.Get_Pause_time();
       glutDisplayFunc(RenderScene_Paused);
       glutKeyboardFunc(tastiera_normale_pausa_giu);
       glutIdleFunc(NULL);
       glutKeyboardUpFunc(NULL);
       glutSpecialFunc(NULL);
       glutSpecialUpFunc(NULL);
       glutMotionFunc(NULL);
       glutMouseFunc(NULL);
       
    break;
    case  127: glutLeaveGameMode();   exit(0) ;   break;
    case  120: elic.SetShootWR();   break;
    case  122: elic.SetShootHR();   break;
    case  99:  elic.SetShootB();    break;
    case  97:  state.translating = 1; break;
    case  100: state.translating = 2; break;
    case  119: state.translating = 3; break;
    case  115: state.translating = 4; break;
}
}

void tastiera_normale_su(unsigned char tasto, int x, int y) {
switch(tasto) {
    
    case  120: elic.UnsetShootWR();   break;
    case  122:  elic.UnsetShootHR();  break;
    case  99:  elic.UnsetShootB();   break;
    case  100:
    case  119:
    case  115:
    case  97: state.translating = 0;   break;
}
}


void tastiera_speciale_su(int tasto, int x, int y)
{
    switch(tasto) {
        case GLUT_KEY_UP :     state.moving = 0;   break;
        case GLUT_KEY_RIGHT :  state.rotating = 0; break;
        case GLUT_KEY_LEFT  :  state.rotating = 0; break;
    }
}

void tastiera_speciale_giu(int tasto, int x, int y) {


switch(tasto) {
    case GLUT_KEY_UP :     state.moving =  1;   break;
    case GLUT_KEY_RIGHT :  state.rotating =  1; break;
    case GLUT_KEY_LEFT  :  state.rotating = -1; break;
    
    
   
    case GLUT_KEY_F1:  camera.Camera_Fullscreen();    break;
    case GLUT_KEY_F2:  camera.ChangeView();    break;
    case GLUT_KEY_F3:  state.th->ChangeFilter();    break;   
    case GLUT_KEY_F4:  state.th->ChangePoligonMode();    break;
    case GLUT_KEY_F5:  camera.ChangeMotionBlur();  break;
    case GLUT_KEY_F6:  
                       if (!state.luce)  light.SetLightOn(),state.luce = true;
                       else light.SetLightOf(),state.luce = false;
    break; 
    
}


glutPostRedisplay();
}

void elabora_tempo_vuoto() {
    
 
    if (state.gameend)
    {
       camera.Save();
       glutDisplayFunc(RenderScene_End);
       glutKeyboardFunc(tastiera_normale_fine_giu);
       glutIdleFunc(NULL);
       glutKeyboardUpFunc(NULL);
       glutSpecialFunc(NULL);
       glutSpecialUpFunc(NULL);
       glutMotionFunc(NULL);
    }
    
    if(!state.camera_pos)      camera.DoIdle();
    else                       camera.DoIdle_Start_Pos();
    
    if (state.takeoff) elic.DoIdle();
    else               elic.DoIdleTakeoff();
    
    sky.DoIdle();
    fotoid.DoIdle();
    game.DoIdle();
    //map.DoIdle();
    
    state.targ->DoIdle();
    for (int i = 0;i <= state.explosions_counter;i++)
               if(state.explosions[i] != NULL)
               { 
                  if (state.explosions[i]->visible)
                    state.explosions[i]->DoIdle();
                  else  
                    { 
                      delete state.explosions[i];
                      state.explosions[i] = NULL;
                    }
               }
               
    for (int i = 0;i < state.smoke_counter;i++)
               if(state.smokes[i]!= NULL)
               { 
               if( state.smokes[i]->visible) 
                  state.smokes[i]->DoIdle();
               else { 
                      delete state.smokes[i];
                      state.smokes[i] = NULL;
                    }
               }
 
    for (int i = 0;i < state.dust_counter;i++)
              if(state.dusts[i]!= NULL)
              {
              if(state.dusts[i]->visible) 
                 state.dusts[i]->DoIdle();
              else { 
                      delete state.dusts[i];
                      state.dusts[i] = NULL;
                   }
              }           
            
   
  
  glutPostRedisplay();
}

void ridimensiona(int largo, int altop) {
 
 camera.ResizeView(largo,altop);
}


void mouse_movimento(int x, int y)
{
  static int xo =0;
  static int yo =0;
    
 camera.Camera_Mouse_Mov(xo,yo,x,y);
  
 xo = x;
 yo = y;   
 glutPostRedisplay();
}


void mouse_buttons(int b , int s , int x, int y)
{
  if (b == GLUT_RIGHT_BUTTON)
    if(s == GLUT_UP) state.rightbuttondown = false;
    else             state.rightbuttondown = true;
    
    
  if (b == GLUT_LEFT_BUTTON)
    if(s == GLUT_UP) state.leftbuttondown = false;
    else             state.leftbuttondown = true;
}
